--
Brotli
Overview
Brotli is a lossless compression format and algorithm commonly used for HTTP content encoding (Content-Encoding: br) and for compressing files on disk. It typically achieves smaller sizes than gzip on web assets (HTML, CSS, JavaScript) while remaining widely supported by modern clients.
History
- Brotli originated at Google as a compression format optimized for web use, with early adoption driven by browser and web platform needs.
- It was later standardized for HTTP as an IETF specification (RFC 7932), enabling interoperable use across servers, CDNs, and browsers.
Adoption
Brotli is commonly used in:
- Web servers and CDNs to compress text-based responses and static assets
- Build pipelines to precompress
.js,.css, and.svgfiles for efficient delivery - APIs and web apps that negotiate compression via
Accept-Encoding
Maintainer
Maintained by the Brotli open-source community (with an original reference implementation developed at Google).
Best when to use
- Serving static web assets where smaller transfer size improves page load performance
- Precompressing build outputs for predictable, cache-friendly delivery
- Compressing large text-heavy files (logs, JSON exports) for storage and transport
Not suitable when
- You cannot provide a fallback (gzip/identity) for older clients or constrained intermediaries
- You plan to compress dynamic responses containing secrets mixed with attacker-controlled input (risk of compression side-channels)
- CPU budget is tight and you intend to use maximum compression levels on-the-fly
Compatibility notes
-
HTTP negotiation depends on the client’s
Accept-Encoding. Servers should support fallback to gzip (and optionally identity) for broad compatibility. -
Many server stacks can do either dynamic compression (on each request) or static precompression (serving
.brfiles). Static precompression is usually safer for CPU predictability. -
Tooling differences:
- Some systems ship a
brotliCLI. - Some environments use library bindings instead of the CLI (for example, in application runtimes).
- Some systems ship a
Prefer static precompression for immutable assets and use moderate quality levels for good size/CPU balance.
Concepts and how it works
Brotli compression combines:
- LZ77-style back-references (reusing repeated byte sequences)
- Entropy coding (Huffman-like coding)
- Context modeling tuned for common web content patterns
In HTTP, Brotli is typically used like this:
Key operational points:
- Compression level affects CPU time much more than decompression time.
- Static assets benefit most because they are compressed once and served many times.
- Always send
Vary: Accept-Encodingwhen serving different encodings for the same URL.
Installation
Verify first (read-only)
brotli --version
brotli --help
Install via package manager
- Debian/Ubuntu
- Fedora/RHEL family
- Arch
- macOS
- Windows
sudo apt update
sudo apt install brotli
sudo dnf install brotli
sudo pacman -S brotli
brew install brotli
On Windows, the most reliable approach is often to use WSL (Ubuntu) for a Linux-like toolchain, or install Brotli using your preferred Windows package manager if available in your environment.
Verify after installation:
```powershell
brotli --version
```
Common commands and options
Basic syntax
brotli [options] input_file
By default, the CLI writes input_file.br next to the input (unless you specify -o).
Inspect before changing anything (read-only)
Check what files exist and their sizes:
ls -lh input_file input_file.br 2>/dev/null || true
Compress a file
Create input_file.br (default behavior):
brotli input_file
Specify output path:
brotli -o out/input_file.br input_file
Write to stdout (useful in pipelines):
brotli -c input_file > input_file.br
Decompress a file
Decompress to a new output file:
brotli -d -o input_file input_file.br
Decompress to stdout:
brotli -d -c input_file.br > input_file
If you use -f (force), the CLI may overwrite output files. Prefer writing to a new path and verifying the result before replacing any originals.
Important flags (practical)
| Flag | Meaning | Typical use | Notes |
|---|---|---|---|
| -- | |||
-d | Decompress | brotli -d input.br | Input is usually a .br file |
-o <file> | Output file | brotli -o out.br in | Avoids accidental overwrite |
-c | Output to stdout | brotli -c in > out.br | Good for pipelines |
-f | Force overwrite | brotli -f -o out.br in | Use carefully |
-q <0..11> | Quality level | brotli -q 6 in | Higher is smaller but slower to compress |
-w <lgwin> | Window size parameter | brotli -w 22 in | Advanced tuning; affects memory and ratio |
-m <mode> | Content mode | brotli -m text in | Common: generic, text, font |
- For static web assets, start with
-q 6to-q 9. - Reserve
-q 11for offline compression where CPU time is acceptable.
Practical use cases
Precompress static web assets
Precompress build outputs into a separate directory:
mkdir -p dist-br
find dist -type f \( -name "*.js" -o -name "*.css" -o -name "*.html" -o -name "*.svg" -o -name "*.json" \) \
-print0 | xargs -0 -I{} sh -c 'brotli -q 9 -o "dist-br/{}.br" "{}"'
Verify a few outputs:
ls -lh dist/app.js dist-br/dist/app.js.br 2>/dev/null || true
Serve .br assets correctly
To serve precompressed assets, the server must:
- Return
Content-Encoding: brfor the.brrepresentation - Return the original
Content-Typefor the underlying file type - Add
Vary: Accept-Encoding - Fall back to gzip or identity when the client does not accept
br
Configuration details vary by server and framework. Use your server’s official documentation for “static Brotli” or “precompressed assets” and validate headers with curl -I.
Validate HTTP negotiation (read-only)
Check response headers (server must already be configured):
curl -I -H 'Accept-Encoding: br' https://example.com/app.js
Look for:
Content-Encoding: brVary: Accept-Encoding
Troubleshooting
Output is larger than gzip
- Use Brotli primarily for text-based content (
.html,.css,.js,.svg,.json). - For already-compressed formats (
.jpg,.png,.mp4,.zip), compression often provides little benefit and may waste CPU.
Recommended check:
ls -lh file.gz file.br 2>/dev/null || true
Browser downloads a .br file instead of using it
This usually indicates the server is serving the .br file as a normal download, without the required header.
What to verify:
- The response for the original URL includes
Content-Encoding: br - The
Content-Typematches the original asset type (for example, JavaScript) Vary: Accept-Encodingis present
Read-only header check:
curl -I -H 'Accept-Encoding: br' https://example.com/app.js
Decompression fails
Common causes:
- Corrupted or truncated
.brfile - Mismatched toolchain or partial downloads
Try decompressing to stdout and checking exit status:
brotli -d -c input.br > /dev/null
echo $?
Security notes
Avoid compressing responses that combine secrets (tokens, session identifiers) with attacker-controlled input. This is a general risk across HTTP compression methods (Brotli/gzip/deflate) and is especially relevant for dynamic HTML and reflected content.
Operational safeguards:
- Prefer static precompression for immutable public assets.
- Apply resource limits for untrusted decompression paths (application-level limits, timeouts, file size caps).
- Avoid decompressing untrusted data without limits; decompression bombs can exhaust memory or disk.
Quick reference
| Task | Command |
|---|---|
| - | -- |
| Show version/help | brotli --version / brotli --help |
| Compress (default output) | brotli input_file |
| Compress with quality | brotli -q 9 -o input_file.br input_file |
| Compress to stdout | brotli -c input_file > input_file.br |
| Decompress to file | brotli -d -o input_file input_file.br |
| Decompress to stdout | brotli -d -c input_file.br > input_file |
| Force overwrite (use carefully) | brotli -f -o out.br in |
| Validate HTTP headers | curl -I -H 'Accept-Encoding: br' https://example.com/file.js |